//
//  PacketTunnelProvider.swift
//  NMPOMarkHot
//
//  Created by PowerfullClean on 2023/11/1.
//

import NetworkExtension
import PacketProcessor_iOS
//import Shadowsocks_iOS
class PacketTunnelProvider: NEPacketTunnelProvider {

    override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {
        guard let nmpo_vpfo = options?["options"] as? [String : Any] else {
            completionHandler(NEVPNError(.configurationDisabled))
            return
        }
        
        self.nmpo_shadHanderl = completionHandler
        self.nmpo_shadServers = NMPOShadowServers(nmpo_vpfo)
        
        nmpo_shadServers?.start(withConnectivityChecks: false) { [weak self] error in
            if error == .noError {
                self?.nmpo_setNetSeings()
            } else {
                self?.nmpo_shadHanderl?(NEVPNError(.connectionFailed))
            }
        }
    }
    
    private func nmpo_setNetSeings() {
        let ipList = [String]()

        var ipV4ExcludedRoutes = [NEIPv4Route]()
        var ipV6ExcludedRoutes = [NEIPv6Route]()

        ipList.forEach { ip in
            if ip.contains(":") {
                ipV6ExcludedRoutes.append(NEIPv6Route(destinationAddress: ip, networkPrefixLength: 128))
            } else {
                ipV4ExcludedRoutes.append(NEIPv4Route(destinationAddress: ip, subnetMask: "255.255.255.255"))
            }
        }

        let nmpo_ipV4Sting = NEIPv4Settings(addresses: ["192.168.20.2"], subnetMasks: ["255.255.255.0"])
        nmpo_ipV4Sting.includedRoutes = [.default()]
        nmpo_ipV4Sting.excludedRoutes = ipV4ExcludedRoutes

        let nmpo_ipV6Sting = NEIPv6Settings(addresses: ["fd66:f83a:c650::1"], networkPrefixLengths: [120])
        nmpo_ipV6Sting.includedRoutes = [.default()]
        nmpo_ipV6Sting.excludedRoutes = ipV6ExcludedRoutes

        let nmpo_dnsSegs = NEDNSSettings(servers: ["8.8.8.8", "8.8.4.4", "1.1.1.1", "1.0.0.1"])

        let nmpo_routsetting = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "192.168.20.1")
        nmpo_routsetting.ipv4Settings = nmpo_ipV4Sting
        nmpo_routsetting.ipv6Settings = nmpo_ipV6Sting
        nmpo_routsetting.dnsSettings = nmpo_dnsSegs

        setTunnelNetworkSettings(nmpo_routsetting) { error in
            if let error = error {
                self.nmpo_shadHanderl?(error)
                return
            }
            self.nmpo_setSSTunnel()
        }
    }

    private func nmpo_setSSTunnel() {

        if let error = TunnelInterface.setup(with: self.packetFlow) {
            self.nmpo_shadHanderl?(error)
            return
        }

        let port: Int32 = self.nmpo_shadServers!.localSSPort
        TunnelInterface.setIsUdpForwardingEnabled(true)
        TunnelInterface.startTun2Socks(port)

        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            TunnelInterface.processPackets()
        }

        self.nmpo_shadHanderl?(nil)
    }

    override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
        TunnelInterface.stop()
        nmpo_shadServers?.stop({ _ in

        })
        completionHandler()
    }

    override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) {
//        if let msg = String(data: messageData, encoding: String.Encoding.utf8) {
//            if msg == "CANCEL_VPN" {
//                nmpo_shadServers?.stop({ _ in
//                })
//                return
//            }
//        }
        if let handler = completionHandler {
            handler(messageData)
        }
    }

    override func sleep(completionHandler: @escaping () -> Void) {
        completionHandler()
    }
//
    override func wake() {
        // Add code here to wake up.
    }
    private var nmpo_shadServers: NMPOShadowServers?
    private var nmpo_shadHanderl: ((Error?) -> Void)?
}
